﻿// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com

// ReSharper disable CheckNamespace
// ReSharper disable CommentTypo
// ReSharper disable UnusedMember.Global

/* ValueFactories.cs -- фабрики значений для анимации
 * Ars Magna project, http://arsmagna.ru
 */

#region Using directives

using System;
using System.Drawing;

#endregion

#nullable enable

namespace AeroSuite.AnimationEngine;

/// <summary>
/// Фабрики значений для анимации.
/// </summary>
public static class ValueFactories
{
    #region Integer Types

    /// <summary>
    /// Фабрика для беззнаковых байтов.
    /// </summary>
    public static byte ByteFactory
        (
            byte startValue,
            byte targetValue,
            double progress
        )
    {
        return (byte) (startValue + (targetValue - startValue) * progress);
    }

    /// <summary>
    /// Фабрика для байтов со знаком.
    /// </summary>
    public static sbyte SByteFactory
        (
            sbyte startValue,
            sbyte targetValue,
            double progress
        )
    {
        return (sbyte) (startValue + (targetValue - startValue) * progress);
    }

    /// <summary>
    /// Фабрика для 16-битных целых со знаком.
    /// </summary>
    public static short ShortFactory
        (
            short startValue,
            short targetValue,
            double progress
        )
    {
        return (short) (startValue + (targetValue - startValue) * progress);
    }

    /// <summary>
    /// Фабрика для 32-битных целых со знаком.
    /// </summary>
    public static int IntegerFactory
        (
            int startValue,
            int targetValue,
            double progress
        )
    {
        return (int) (startValue + (targetValue - startValue) * progress);
    }

    /// <summary>
    /// Фабрика для 64-битных целых со знаком.
    /// </summary>
    public static long LongFactory
        (
            long startValue,
            long targetValue,
            double progress
        )
    {
        return (long) (startValue + (targetValue - startValue) * progress);
    }

    /// <summary>
    /// Фабрика для 16-битных целых без знака.
    /// </summary>
    public static ushort UnsignedShortFactory
        (
            ushort startValue,
            ushort targetValue,
            double progress
        )
    {
        return (ushort) (startValue + (targetValue - startValue) * progress);
    }

    /// <summary>
    /// Фабрика для 32-битных целых без знака.
    /// </summary>
    public static uint UnsignedIntegerFactory
        (
            uint startValue,
            uint targetValue,
            double progress
        )
    {
        return (uint) (startValue + (targetValue - startValue) * progress);
    }

    /// <summary>
    /// Фабрика для 64-битных целых без знака.
    /// </summary>
    public static ulong UnsignedLongFactory
        (
            ulong startValue,
            ulong targetValue,
            double progress
        )
    {
        return (ulong) (startValue + (targetValue - startValue) * progress);
    }

    #endregion

    #region Floating Point Types

    /// <summary>
    /// Фабрика для чисел с плавающей точкой одинарной точности.
    /// </summary>
    public static float FloatFactory
        (
            float startValue,
            float targetValue,
            double progress
        )
    {
        return (float) (startValue + (targetValue - startValue) * progress);
    }

    /// <summary>
    /// Фабрика для чисел с плавающей точкой двойной точности.
    /// </summary>
    public static double DoubleFactory
        (
            double startValue,
            double targetValue,
            double progress
        )
    {
        return startValue + (targetValue - startValue) * progress;
    }

    #endregion

    #region Drawing

    /// <summary>
    /// Фабрика для точек на плоскости.
    /// </summary>
    public static Point PointFactory
        (
            Point startValue,
            Point targetValue,
            double progress
        )
    {
        return new Point
            (
                IntegerFactory (startValue.X, targetValue.X, progress),
                IntegerFactory (startValue.Y, targetValue.Y, progress)
            );
    }

    /// <summary>
    /// Фабрика для точек на плоскости.
    /// </summary>
    public static PointF PointFFactory
        (
            PointF startValue,
            PointF targetValue,
            double progress
        )
    {
        return new PointF
            (
                FloatFactory (startValue.X, targetValue.X, progress),
                FloatFactory (startValue.Y, targetValue.Y, progress)
            );
    }

    /// <summary>
    /// Фабрика для размеров на плоскости.
    /// </summary>
    public static Size SizeFactory
        (
            Size startValue,
            Size targetValue,
            double progress
        )
    {
        return new Size
            (
                IntegerFactory (startValue.Width, targetValue.Width, progress),
                IntegerFactory (startValue.Height, targetValue.Height, progress)
            );
    }

    /// <summary>
    /// Фабрика для размеров на плоскости.
    /// </summary>
    public static SizeF SizeFFactory
        (
            SizeF startValue,
            SizeF targetValue,
            double progress
        )
    {
        return new SizeF
            (
                FloatFactory (startValue.Width, targetValue.Width, progress),
                FloatFactory (startValue.Height, targetValue.Height, progress)
            );
    }

    /// <summary>
    /// Фабрика для прямоугольников.
    /// </summary>
    public static Rectangle RectangleFactory
        (
            Rectangle startValue,
            Rectangle targetValue,
            double progress
        )
    {
        return new Rectangle
            (
                IntegerFactory (startValue.X, targetValue.X, progress),
                IntegerFactory (startValue.Y, targetValue.Y, progress),
                IntegerFactory (startValue.Width, targetValue.Width, progress),
                IntegerFactory (startValue.Height, targetValue.Height, progress)
            );
    }

    /// <summary>
    /// Фабрика для прямоугольников.
    /// </summary>
    public static RectangleF RectangleFFactory
        (
            RectangleF startValue,
            RectangleF targetValue,
            double progress
        )
    {
        return new RectangleF
            (
                FloatFactory (startValue.X, targetValue.X, progress),
                FloatFactory (startValue.Y, targetValue.Y, progress),
                FloatFactory (startValue.Width, targetValue.Width, progress),
                FloatFactory (startValue.Height, targetValue.Height, progress)
            );
    }

    /// <summary>
    /// Фабрика для цветов в формате RGB.
    /// </summary>
    public static Color ColorRgbFactory
        (
            Color startValue,
            Color targetValue,
            double progress
        )
    {
        return Color.FromArgb
            (
                IntegerFactory (startValue.A, targetValue.A, progress),
                IntegerFactory (startValue.R, targetValue.R, progress),
                IntegerFactory (startValue.G, targetValue.G, progress),
                IntegerFactory (startValue.B, targetValue.B, progress)
            );
    }

    #endregion

    #region Other

    /// <summary>
    /// Фабрика для логических значений.
    /// </summary>
    public static bool BooleanFactory
        (
            bool startValue,
            bool targetValue,
            double progress
        )
    {
        return progress < .5 ? startValue : targetValue;
    }

    /// <summary>
    /// Фабрика для чисел с фиксированной точкой.
    /// </summary>
    public static decimal DecimalFactory
        (
            decimal startValue,
            decimal targetValue,
            double progress
        )
    {
        return startValue + (targetValue - startValue) * (decimal) progress;
    }

    /// <summary>
    /// Фабрика для промежутков времени.
    /// </summary>
    public static TimeSpan TimeSpanFactory
        (
            TimeSpan startValue,
            TimeSpan targetValue,
            double progress
        )
    {
        return startValue.Add
            (
                TimeSpan.FromMilliseconds (targetValue.Subtract (startValue).TotalMilliseconds * progress)
            );
    }

    #endregion
}
